package com.zgg.task;

import com.alibaba.fastjson.JSONObject;
import com.zgg.config.AliOssProperties;
import com.zgg.files.service.impl.UploadServiceImpl;
import com.zgg.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;

/**
 * 失败的文件会一小时重新上传
 */
@EnableScheduling
@Component
public class FailureFileUploadScheduled {
    private Logger logger = LoggerFactory.getLogger(FailureFileUploadScheduled.class);

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private Environment env;

    @Autowired
    private UploadServiceImpl uploadService;
    @Autowired
    private AliOssProperties aliOssProperties;
    //一天
    private long oneTime = 1000 * 60 * 60 * 24;

    @Autowired
    private CallbackUtils callbackUtils;

    private String failure_file_dingding = "https://oapi.dingtalk.com/robot/send?access_token=5bb114c263dbb45d44e26d0a9a9ed8687caa11073b45cbac458451df901f0bf3";

    @Scheduled(cron = "0 0 0/1 * * * ")
    public void removeTempFile() {
        logger.error("==========>>>>>    失败文件重新上传定时任务开始执行......");
        long startTime = System.currentTimeMillis();
        //获取所有上传失败的文件
        List<File> fileList = FileUtils.getFilePathList(env.getProperty("ali.localUrl"));

        /**
         * 扫描所有临时目录下的文件
         */
        for (File file : fileList) {
            BasicFileAttributes bAttributes = null;
            try {
                bAttributes = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //文件最后修改时间
            String changeTime = bAttributes.lastModifiedTime().toString();
            StringBuffer time = new StringBuffer();
            time.append(changeTime.substring(0, 10)).append(" ").append(changeTime.substring(11, 19));
            Date date = DateUtils.getDateByFormat(time.toString(), "yyyy-MM-dd HH:mm:ss");
            Date changeDate = DateUtils.addDate(date, 3, 8);
            long timeDifference = System.currentTimeMillis() - changeDate.getTime();
            //获取缓存中对应文件的callbackbody
            String callbackBodyString = redisUtils.get(AliOssProperties.uploadFileCache + file.getName());

            //上传失败的文件大于一天并小于30天，重新上传。否则直接删除
            if (timeDifference > oneTime && timeDifference < oneTime * 30) {
                if (callbackBodyString != null && !"".equals(callbackBodyString)) {
                    String[] strings = callbackBodyString.split("\\|\\|");
                    String fileId = strings[0];
                    String callbackBody = strings[1];
                    Map<String, String> fileMap = new HashMap<>();
                    fileMap.put(file.getPath(), fileId);
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("callbackBody", callbackBody);
                    jsonObject.put("sign", "");
                    jsonObject.put("code", "");
                    uploadService.uploadOSSFile(fileMap, aliOssProperties, jsonObject);
                } else {
                    logger.warn("======>>>>   没有在缓存中找到文件【" + file.getPath() + "】信息！");
                }
            } else {
                FileUtils.removeFilePath(file.getPath());
                logger.error("======>>>>   时间超过30天，删除临时文件【" + file.getPath() + "】！");
            }
        }

        /**
         * 所有缓存中的失败回调
         */
        Set<String> failureKeySet = redisUtils.keys(AliOssProperties.uploadFileFailureCache + "*");
        logger.error("========>>>>>   失败回调的次数：" + failureKeySet.size());
        for (String failureKey : failureKeySet) {
            //获取回调失败次数
            if (redisUtils.exists(failureKey + "_count")) {
                int failureCount = Integer.parseInt(redisUtils.get(failureKey + "_count"));

                String callbackBodyString = redisUtils.get(failureKey);
                String[] strings = callbackBodyString.split("\\|\\|");
                String fileId = strings[0];
                String callbackBody = strings[1];

                //回调失败次数小于5次再次回调，否则钉钉告警
                if (failureCount <= 5) {
                    callbackUtils.clientCallBack(callbackBody, failureKey.replace(AliOssProperties.uploadFileFailureCache, ""), fileId);
                } else {
                    String callbackContent = BASE64Utils.decode(callbackBody);
                    logger.info("=========>>>>>>>      clientCallBackBody 反编码后的结果：【" + callbackContent + "】");

                    JSONObject clientCallBackJson = null;
                    try {
                        clientCallBackJson = JSONObject.parseObject(callbackContent);
                    } catch (Exception ex) {
                        logger.error("============>>>>>>   clientCallBackBody转换json失败");
                    }

                    StringBuffer content = new StringBuffer();
                    content.append("文件：【").append(failureKey.replace(AliOssProperties.uploadFileFailureCache, ""))
                            .append("】，回调地址：【" + clientCallBackJson.getString("url") + "】次数已经重试超过50次，请重新上传！");
                    //回调超过5次失败后从缓存中删除并调用dingding通知
                    redisUtils.delete(failureKey + "_count");
                    redisUtils.delete(failureKey);
                    DingdingUtil.dingDingChatbotSend(failure_file_dingding, "文件回调失败", content.toString(), new ArrayList<String>());
                }
            }
        }
        long endTime = System.currentTimeMillis();
        logger.error("==========>>>>>    失败文件重新上传定时任务执行结束,总共耗时：【" + (endTime - startTime) + "】");
    }


}
